package masterjava.common.configuration.store.apache;

import masterjava.common.configuration.store.AbstractPropertiesStore;
import masterjava.common.property.Property;
import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;

import java.util.Iterator;

/**
 * MasterJava.ru
 * <p/>
 * User: GKislin
 * Date: 02.03.11
 *
 * @see org.apache.commons.configuration.AbstractConfiguration based configuration
 */
abstract public class ApacheConfigurationStore<C extends AbstractConfiguration> extends AbstractPropertiesStore {

    // static initializer
    protected static class PropertyConfigurationListener implements ConfigurationListener {
        private final Property<?> prop;

        public PropertyConfigurationListener(Property<?> prop) {
            this.prop = prop;
        }

        @Override
        public void configurationChanged(ConfigurationEvent event) {
            if (prop.getKey().equals(event.getPropertyName()) && !event.isBeforeUpdate()) {
                /** Notify AFTER change, as logic could depend of changed Configuration
                 * @see masterjava.common.configuration.setting.UrlSetting#createProp()
                 */
                switch (event.getType()) {
                    case AbstractConfiguration.EVENT_ADD_PROPERTY:
                    case AbstractConfiguration.EVENT_SET_PROPERTY:
                    case AbstractConfiguration.EVENT_CLEAR_PROPERTY:
                        prop.reInitValue();
                        break;
                    default:
                        throw LOGGER.getIllegalStateException("Illegal Configuration event.");
                }
            }
        }
    }

    protected final C configuration;

    protected ApacheConfigurationStore(C configuration) {
        this.configuration = configuration;
    }

    public C getConfiguration() {
        return configuration;
    }

    @Override
    public String getProperty(String key) {
        return (String) configuration.getProperty(key);
    }

    @Override
    public void setProperty(String key, String newValue) {
        throw LOGGER.getIllegalStateException("Illegal setting property " + key + " to Configuration with notification.");
    }

    // Add property change listener
    @Override
    public void addConfigurationListener(Property<?> prop) {
        configuration.addConfigurationListener(new PropertyConfigurationListener(prop));
    }

    @Override
    public Iterator<String> getKeysIterator() {
        return (Iterator<String>) configuration.getKeys();
    }
}
